package com.runmonk.core.util;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;

/**
 * 函数式编程工具类
 *
 * @author chaobo
 * @since 2019/9/5
 */
public class StreamUtil {

    /**
     * map 方法转List 示例如下
     * [7, 2, 6]
     * List<Integer> l = map(
     *      Arrays.asList("lambdas","in","action"),
     *      (String s) -> s.length()
     * );
     * @return
     */
    public static <T,R> List<R> mapToList(List<T> list, Function<T,R> function) {
        if (CollectionUtil.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<R> result = new ArrayList<>();
        for(T s: list){
            result.add(function.apply(s));
        }
        return result;
    }

    /**
     * map 方法转Set 示例如下
     * [7, 2, 6]
     * List<Integer> l = map(
     *      Arrays.asList("lambdas","in","action"),
     *      (String s) -> s.length()
     * );
     * @return
     */
    public static <T,R> Set<R> mapToSet(List<T> list, Function<T,R> function) {
        if (CollectionUtil.isEmpty(list)) {
            return new HashSet<>();
        }

        Set<R> result = new HashSet<>();
        for(T s: list){
            result.add(function.apply(s));
        }
        return result;
    }

    public static <T> List<T> filter(List<T> list, Predicate<T> p) {
        List<T> results = new ArrayList<>();
        for(T s: list){
            if(p.test(s)){
                results.add(s);
            }
        }
        return results;
    }

    /**
     * 去重 示例如下
     *
     * .filter(distinctByKey(o -> o.getPointc().getX()))
     */
    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
}
